﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports System
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.IO
Imports System.Linq
Imports System.Web
Imports System.Xml.Serialization

Namespace roncliProductions.LibWowArmory.TalentTree

    ''' <summary>
    ''' A class that retrieves class talents from the armory
    ''' </summary>
    ''' <remarks></remarks>
    Public Class TalentTree
        Inherits WowArmoryData

        Private ttPage As New Schema.page
        Private lstTalentTrees As New Collection(Of Tree)

        ''' <summary>
        ''' The class to lookup talents for
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property [Class] As Enums.ClassType

        ''' <summary>
        ''' The talent trees for this class
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property TalentTrees As Collection(Of Tree)
            Get
                Return lstTalentTrees
            End Get
        End Property

        ''' <summary>
        ''' The URL that will be used to retrieve the class's talents from the armory
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property URL As String
            Get
                If [Class] = Enums.ClassType.Unknown Then
                    Return "http://www.wowarmory.com/talent-tree.xml?cid=&loc=en_us"
                Else
                    Return String.Format(CultureInfo.InvariantCulture, "http://www.wowarmory.com/talent-tree.xml?cid={0}&loc=en_us", CInt([Class]))
                End If
            End Get
        End Property

        ''' <summary>
        ''' Indicates to the inherited class that this request does not require login
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property RequiresLogin As Boolean
            Get
                Return False
            End Get
        End Property

        ''' <summary>
        ''' A constructor to load a class's talents
        ''' </summary>
        ''' <param name="cClass"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal cClass As Enums.ClassType)
            [Class] = cClass
            Load()
        End Sub

        ''' <summary>
        ''' A constructor to load a class's talents
        ''' </summary>
        ''' <param name="strClass"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal strClass As String)
            If String.IsNullOrEmpty(strClass) Then Throw New ArgumentException("Class cannot be null or empty.")
            Try
                [Class] = CType([Enum].Parse(GetType(Enums.ClassType), strClass.Replace(" ", "")), Enums.ClassType)
            Catch ex As Exception
                Throw New ArgumentException("There is no such class.")
            End Try
            Load()
        End Sub

        ''' <summary>
        ''' Loads the class's talents from the Armory
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Load()
            Dim strKey As String = String.Format(CultureInfo.InvariantCulture, "LibWowArmory.TalentTree.{0}", CInt([Class]))
            If Cache.Cache(strKey) Is Nothing Then
                MyBase.Retrieve()

                Dim xsSerializer As New XmlSerializer(ttPage.GetType)

                Using srXML As New StringReader(MyBase.Data)
                    ttPage = CType(xsSerializer.Deserialize(srXML), Schema.page)
                End Using

                Cache.Cache.Insert(strKey, ttPage, Nothing, Date.UtcNow.AddDays(1), Nothing, Caching.CacheItemPriority.Normal, Nothing)
            Else
                ttPage = CType(Cache.Cache(strKey), Schema.page)
            End If

            Dim intTalentID As Integer = 0
            Dim ttsTree As Schema.tree
            Dim ttsTalent As Schema.talent
            Dim ttsRank As Schema.rank
            Dim tTree As Tree
            Dim tTalent As Talent
            For Each ttsTree In ttPage.talentTrees.First.tree.OrderBy(Function(t) t.order)
                tTree = New Tree(ttsTree.name)
                For Each ttsTalent In ttsTree.talent.OrderBy(Function(t) t.tier).ThenBy(Function(t) t.column)
                    tTalent = New Talent(intTalentID, ttsTalent.name, ttsTalent.key, 0, ttsTalent.rank.Count, ttsTalent.column, ttsTalent.tier, ttsTalent.requires)
                    For Each ttsRank In ttsTalent.rank.OrderBy(Function(t) t.level)
                        tTalent.Ranks.Add(ttsRank.description)
                    Next
                    If ttsTalent.spell.Count > 0 Then
                        tTalent.SpellCastTime = ttsTalent.spell.First.castTime
                        tTalent.SpellCooldown = ttsTalent.spell.First.cooldown
                        tTalent.SpellMaxRange = ttsTalent.spell.First.maxRange
                        If ttsTalent.spell.First.power.Count > 0 Then
                            For Each pPower As Schema.power In ttsTalent.spell.First.power
                                tTalent.RequiredPower.Add(New Power(pPower.cost, pPower.type))
                            Next
                        End If
                    End If
                    tTree.Talents.Add(tTalent)
                    intTalentID += 1
                Next
                lstTalentTrees.Add(tTree)
            Next
        End Sub

        ''' <summary>
        ''' Retrieves the talent by its talent ID
        ''' </summary>
        ''' <param name="intTalentID"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetTalentByID(ByVal intTalentID As Integer) As Talent
            Dim varTalents = lstTalentTrees.SelectMany(Function(t) t.Talents).Where(Function(t) t.TalentID = intTalentID)
            If varTalents.Count = 0 Then
                'Throw New ArgumentOutOfRangeException("intTalentID", "The talent ID does not exist for this class.")
                Return Nothing
            Else
                Return varTalents.First
            End If
        End Function

    End Class

End Namespace